{\bf Celem} jest uniezależnienie konkretnego obiektu obserwowanego od
konkretnego obserwatora.
To z kolei pozwala osiągnąć łatwość
dodawania i usuwania obserwatorów.

\noindent
Relacja jeden do wielu:
Jeden obiekt obserwowany może mieć wielu obserwatorów. 

{\small {\bf Uwaga.} W cytowanym kodzie dla uproszczenia pomijam \#define, \#include, using.}

\paragraph{Jeden obserwator.}
Zaczynam od dołączenia tylko jednego obserwatora.
Jednak od razu wymuszam, aby korzystał on
z odpowiednich interfejsów.

\noindent
{\bf Interfejs obserwatora.}
Deklaruje czysto wirtualną metodę {\tt update()}.
Jest to interfejs działań obserwatora,
posiada argument {\tt Obserwowany*},
aby wywoływać metody obserwowanej klasy.
\begin{lstCpp}
class Obserwowany;

class Obserwator {
public:
  virtual void update(Obserwowany*) = 0;
};
\end{lstCpp}


Klasa {\tt Obserwowany} 
będzie stanowić klasę bazową dla konkretnych 
klas obserwowanych. 
Przechowuje ona
\begin{itemize}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item listę wskaźników do obiektów implementujących interfejs
 {\tt Obserwator}
\end{itemize}
\vspace{-6pt}
Dostarcza ona funkcjonalności obsługującej obserwatorów
\begin{itemize}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item {\tt attach()} dodawanie obiektów implementujących  {\tt Obserwator}
 do listy
\item {\tt detach()} usuwanie obiektów implementujących  {\tt Obserwator}
 do listy
\item {\tt notify()} zawiadamianie wszystkich obserwatorów z listy;
 dla każdego z nich wywołujemy metodę aktualizacji {\tt update()}
\end{itemize}
\vspace{-6pt}
\begin{lstCpp}
class Obserwowany {
private:
  list<Obserwator*> obserwatorzy;
public:
  virtual ~Obserwowany() { }
  virtual void attach(Obserwator* ob) { obserwatorzy.push_back(ob); }
  virtual void detach(Obserwator* ob) { obserwatorzy.remove(ob); }
  virtual void notify() {
    list<Obserwator*>::iterator it;
    for(it = obserwatorzy.begin(); it != obserwatorzy.end(); ++it) {
      (*it)->update(this);
    }
  }
};
\end{lstCpp}

Konkretna klasa obserwowana. 
Publicznie ona dziedziczy całą funkcjonalność
związaną z listą obserwatorów.
\begin{lstCpp}
class Pacjent : public Obserwowany {
private:
  int cisnienieSkurczowe;
  int cisnienieRozkurczowe;
public:
  Pacjent() : cisnienieSkurczowe(120), cisnienieRozkurczowe(80) { }
  int getCisnienieSkurczowe()   { return cisnienieSkurczowe; }
  int getCisnienieRozkurczowe() { return cisnienieRozkurczowe; }
  void setCisnienieSkurczowe(int c)   { cisnienieSkurczowe = c; }
  void setCisnienieRozkurczowe(int c) { cisnienieRozkurczowe = c; }
  void zwiekszCisnienia() { 
    cisnienieSkurczowe += 10; 
    cisnienieRozkurczowe += 5;
  }
  
};
\end{lstCpp}

Konkretny obserwator implementuje metodę {\tt update()}. 
\begin{lstCpp}
class MiernikSkurczowego : public Obserwator {
public:
  virtual void update(Obserwowany* ob);
};

void MiernikSkurczowego::update(Obserwowany* ob) {
  Pacjent* p = dynamic_cast<Pacjent*>(ob);
  if (p) {
    cout << "Cisnienie skurczowe = " << p->getCisnienieSkurczowe() << endl;
	if ( p->getCisnienieSkurczowe() > 180 ) {
      cout << "Cisnienie skurczowe zbyt wysokie... odpoczywam" << endl;
      p->setCisnienieSkurczowe(120);
      p->setCisnienieRozkurczowe(80);
	  sleep(1);
	  this->update(p);
	}
  }
}
\end{lstCpp}

Główny program.
Wyświetla menu w pętli.
\begin{lstCpp}
void wyswietlMenu() {
  cout << "1) Pokaz menu" << endl;
  cout << "2) Biegnij" << endl;
  cout << "3) Koncz" << endl;
}

int main() {
  Pacjent *pac = new Pacjent;
  Obserwator *mSkurcz  = new MiernikSkurczowego();
  pac->attach(mSkurcz);
  
  // w petli
  wyswietlMenu();
  int wybor = 0;
  while (wybor != 3) {
    cin >> wybor;
    switch (wybor) {
      case 1:
        wyswietlMenu(); break;
      case 2:
        cout << "Biegne..." << endl;
        pac->zwiekszCisnienia();
        pac->notify(); // zawiadamiam obserwatory na liscie
        wyswietlMenu(); break;
      case 3:
        cout << "Koncze bieganie." << endl; break;
	}
  }
  
  delete pac;
  delete mSkurcz;
  return 0;
}
\end{lstCpp}

\paragraph{Dodanie drugiego obserwatora.}
Załóżmy, że chcę utworzyć obserwator ciśnienia rozkurczowego.
Definiuję klasę implementującą interfejs {\tt Obserwator}.
\begin{lstCpp}
class MiernikRozkurczowego : public Obserwator {
public:
  virtual void update(Obserwowany* ob);
};

void MiernikRozkurczowego::update(Obserwowany* ob) {
  Pacjent* p = dynamic_cast<Pacjent*>(ob);
  if (p) {
    cout << "Cisnienie rozkurczowe = " << p->getCisnienieRozkurczowe() << endl;
    if ( p->getCisnienieRozkurczowe() > 109 ) {
      cout << "Cisnienie rozkurczowe zbyt wysokie... odpoczywam" << endl;
      p->setCisnienieSkurczowe(120);
      p->setCisnienieRozkurczowe(80);
      sleep(1);
      this->update(p);
    }
  }
}
\end{lstCpp}

Zmiany w pliku {\sf main.cpp} można
sprawdzić {\tt git diff}, jeżeli wersje zapisano w różnych commitach.
 {\small
\begin{lstV}
$ git diff b5ca c6cb ./cpp/algorytm/wzorce/observer-1/main.cpp
diff --git a/cpp/algorytm/wzorce/observer-1/main.cpp b/cpp/algorytm/wzorce/obser
index 475b166..e32cb82 100644
--- a/cpp/algorytm/wzorce/observer-1/main.cpp
+++ b/cpp/algorytm/wzorce/observer-1/main.cpp
@@ -1,5 +1,4 @@
 #include "MiernikSkurczowego.h"
-#include "MiernikRozkurczowego.h"
 #include "Pacjent.h"

 #include <iostream>
@@ -15,9 +14,7 @@ void wyswietlMenu() {
 int main() {
   Pacjent *pac = new Pacjent;
   Obserwator *mSkurcz  = new MiernikSkurczowego();
-  Obserwator *mRozkurcz  = new MiernikRozkurczowego();
   pac->attach(mSkurcz);
-  pac->attach(mRozkurcz);

   // w petli
   wyswietlMenu();
@@ -39,6 +36,5 @@ int main() {

   delete pac;
   delete mSkurcz;
-  delete mRozkurcz;
   return 0;
 }
\ No newline at end of file
\end{lstV}
}

\paragraph{Podsumowanie.}
Przejrzyjmy zmiany w kodzie głównego pliku,
gdy dodaję nowy obserwator.
\begin{itemize}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item Dołączam nagłówek z definicją klasy
\begin{lstCpp}
#include "MiernikRozkurczowego.h"
\end{lstCpp}
\item
Tworzę instancję drugiego  obserwatora.
\begin{lstCpp}
Obserwator *mRozkurcz  = new MiernikRozkurczowego();
\end{lstCpp}
\item
Dołączam drugiego obserwatora do obiektu obserwowanego.
\begin{lstCpp}
pac->attach(mRozkurcz);
\end{lstCpp}
\item
Usuwam instancję drugiego  obserwatora.
\begin{lstCpp}
delete mRozkurcz;
\end{lstCpp}
\end{itemize}
Zalety
\begin{enumerate}\setlength\itemsep{-2pt}\setlength\topsep{-2pt}\vspace{-6pt}
\item Nie ma ingerencji w kod obiektu obserwowanego {\tt Pacjent}.
\item Cały czas posługujemy się tym samym interfejsem klasy {\tt Obserwowany}.
\item Nie ma ingerencji w kod głównej pętli programu.
\end{enumerate}

\includegraphics[scale=0.7]{rys/algorytm-wzorce-observer-1}